package com.jdrx.sw.sewage.service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jdrx.sw.sewage.beans.vo.DeviceFailureAnalysisVO;
import com.jdrx.sw.sewage.beans.vo.DeviceFailureVO;
import com.jdrx.sw.sewage.beans.vo.DeviceMaintenanceAnalysisVO;
import com.jdrx.sw.sewage.beans.vo.DeviceOverviewAnalysisVO;
import com.jdrx.sw.sewage.beans.vo.DeviceRunTimeAnalysisVO;
import com.jdrx.sw.sewage.beans.vo.DeviceRunTimeVO;
import com.jdrx.sw.sewage.beans.vo.DeviceSpareAnalysisVO;
import com.jdrx.sw.sewage.dao.WorkOrderDAO;

/**
 * 设备分析
 * @author Administrator
 *
 */
@Service
public class DeviceAnalysisService {
	@Autowired
	private WorkOrderDAO workOrderDAO;
	
	/**
	 * 设备概览分析
	 * @return
	 */
	public DeviceOverviewAnalysisVO overview() {
		// 设备库存数量
		int deviceStoreAmount = workOrderDAO.countByUnused();
		// 设备故障总次数
		int deviceFailureCount = workOrderDAO.countByFailure();
		// 单设备连续时长最大值
		Double maxSustainRunTime = workOrderDAO.maxContinueRunTime();
		// 总电器设备数
		int deviceAmount = workOrderDAO.countByElectricalDevice();
		// 当前运行设备数：最近5分钟内采集了数据的设备
		LocalDateTime now = LocalDateTime.now();
		int runDeviceAmount = workOrderDAO.countByCurrentRunDevice(now.minusMinutes(5), now);
		
		DeviceOverviewAnalysisVO vo = new DeviceOverviewAnalysisVO();
		vo.setDeviceStoreAmount(deviceStoreAmount);
		vo.setDeviceFailureCount(deviceFailureCount);
		vo.setMaxSustainRunTime(maxSustainRunTime);
		vo.setRunDeviceAmount(runDeviceAmount);
		vo.setDeviceAmount(deviceAmount);
		return vo;
	}
	
	/**
	 * 设备保养分析
	 * @return
	 */
	public DeviceMaintenanceAnalysisVO maintenanceAnalysis() {
		// 已保养设备数量
		int alreadyAmount = workOrderDAO.countByAlreadyMaintenance();
		// 即将保养设备数量
		int upcomingAmount = workOrderDAO.findMaintenanceDevList().size();
		// 保养过期设备数量
		int expireAmount = workOrderDAO.countByExpireMaintenance();
		
		/*计算占比百分比*/
		// 总数量
		int total = alreadyAmount + upcomingAmount + expireAmount;
		
		double alreadyPercent = 0;
		double upcomingPercent = 0;
		double expirePercent = 0;
		if(total > 0) {
			// 已保养设备占比
			alreadyPercent = new BigDecimal(alreadyAmount).divide(new BigDecimal(total), BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_UP).doubleValue();
			// 即将保养设备占比
			upcomingPercent = new BigDecimal(upcomingAmount).divide(new BigDecimal(total), BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_UP).doubleValue();
			// 保养过期设备占比
			expirePercent = new BigDecimal(expireAmount).divide(new BigDecimal(total), BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_UP).doubleValue();
		}
		
		DeviceMaintenanceAnalysisVO vo = new DeviceMaintenanceAnalysisVO();
		vo.setAlreadyAmount(alreadyAmount);
		vo.setUpcomingAmount(upcomingAmount);
		vo.setExpireAmount(expireAmount);
		vo.setAlreadyPercent(alreadyPercent);
		vo.setUpcomingPercent(upcomingPercent);
		vo.setExpirePercent(expirePercent);
		return vo;
	}
	
	/**
	 * 设备备件分布情况
	 * @return
	 */
	public List<DeviceSpareAnalysisVO> spareAnalysis() {
		return workOrderDAO.spareAnalysis();
	}
	
	/**
	 * 设备故障统计TOP10
	 * @return
	 */
	public List<DeviceFailureAnalysisVO> failureAnalysis() {
		/*统计当月设备故障次数*/
		// 当月第一天
		LocalDate monthFirstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
		LocalDateTime startTime = LocalDateTime.of(monthFirstDay, LocalTime.of(0, 0, 0));
		// 当月最后一天
		LocalDate monthLastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
		LocalDateTime endTime = LocalDateTime.of(monthLastDay, LocalTime.of(23, 59, 59));
		// 查询当月设备故障次数
		List<DeviceFailureVO> currentMonth = workOrderDAO.failureAnalysis(startTime, endTime);
		
		/*统计上月设备故障次数*/
		// 上月第一天
		monthFirstDay = LocalDate.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
		startTime = LocalDateTime.of(monthFirstDay, LocalTime.of(0, 0, 0));
		// 上月最后一天
		monthLastDay = LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
		endTime = LocalDateTime.of(monthLastDay, LocalTime.of(23, 59, 59));
		// 查询上月设备故障次数
		List<DeviceFailureVO> lastMonth = workOrderDAO.failureAnalysis(startTime, endTime);
		
		/*统计去年当月设备故障次数*/
		// 去年当月第一天
		//monthFirstDay = LocalDate.now().minusYears(1).with(TemporalAdjusters.firstDayOfMonth());
		//startTime = LocalDateTime.of(monthFirstDay, LocalTime.of(0, 0, 0));
		// 去年当月最后一天
		//monthLastDay = LocalDate.now().minusYears(1).with(TemporalAdjusters.lastDayOfMonth());
		//endTime = LocalDateTime.of(monthLastDay, LocalTime.of(23, 59, 59));
		// 查询去年当月设备故障次数
		//List<DeviceFailureVO> lastYearMonth = workOrderDAO.failureAnalysis(startTime, endTime);
		
		/*以当月设备故障次数为基准计算环比、同比*/
		Map<String, DeviceFailureVO> lastMonthMap = lastMonth.stream()
				.collect(Collectors.toMap(DeviceFailureVO :: getName, Function.identity(), (key1, key2) -> key2));
		//Map<String, DeviceFailureVO> lastYearMonthMap = lastYearMonth.stream()
				//.collect(Collectors.toMap(DeviceFailureVO :: getName, Function.identity(), (key1, key2) -> key2));
		
		List<DeviceFailureAnalysisVO> list = Lists.newArrayList();
		for(DeviceFailureVO failureVO : currentMonth) {
			DeviceFailureAnalysisVO vo = new DeviceFailureAnalysisVO();
			vo.setName(failureVO.getName());
			vo.setCurrentMonthCount(failureVO.getFailureCount());
			vo.setLastMonthCount(Optional.ofNullable(lastMonthMap.get(failureVO.getName())).map(t -> t.getFailureCount()).orElse(null));
			//vo.setLastYearMonthCount(Optional.ofNullable(lastYearMonthMap.get(failureVO.getName())).map(t -> t.getFailureCount()).orElse(null));
			list.add(vo);
		}
		return list;
	}
	
	/**
	 * 设备运行时长top10
	 * @return
	 */
	public List<DeviceRunTimeAnalysisVO> runTimeAnalysisTop10() {
		return workOrderDAO.findLJYXSJByTop10();
	}
	
	/**
	 * 设备运行时长top10
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	@Deprecated
	public List<DeviceRunTimeAnalysisVO> runTimeAnalysis() {
		/*统计当月设备运行时长*/
		// 当月第一天
		LocalDate monthFirstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
		LocalDateTime startTime = LocalDateTime.of(monthFirstDay, LocalTime.of(0, 0, 0));
		// 当月最后一天
		LocalDate monthLastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
		LocalDateTime endTime = LocalDateTime.of(monthLastDay, LocalTime.of(23, 59, 59));
		List<Map<String, Object>> currentMonth = this.calculateDeviceRunTime(startTime, endTime);
		
		/*统计上月设备运行时长*/
		// 上月第一天
		monthFirstDay = LocalDate.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
		startTime = LocalDateTime.of(monthFirstDay, LocalTime.of(0, 0, 0));
		// 上月最后一天
		monthLastDay = LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
		endTime = LocalDateTime.of(monthLastDay, LocalTime.of(23, 59, 59));
		// 查询上月设备运行时长
		List<Map<String, Object>> lastMonth = this.calculateDeviceRunTime(startTime, endTime);
		
		/*统计去年当月设备运行时长*/
		// 去年当月第一天
		monthFirstDay = LocalDate.now().minusYears(1).with(TemporalAdjusters.firstDayOfMonth());
		startTime = LocalDateTime.of(monthFirstDay, LocalTime.of(0, 0, 0));
		// 去年当月最后一天
		monthLastDay = LocalDate.now().minusYears(1).with(TemporalAdjusters.lastDayOfMonth());
		endTime = LocalDateTime.of(monthLastDay, LocalTime.of(23, 59, 59));
		// 查询去年当月设备运行时长
		List<Map<String, Object>> lastYearMonth = this.calculateDeviceRunTime(startTime, endTime);
		
		/*以当月设备运行时长为基准计算环比、同比*/
		Map<String, Map<String, Object>> lastMonthMap = lastMonth.stream()
				.collect(Collectors.toMap(t -> MapUtils.getString(t, "gatherDevId"), Function.identity(), (key1, key2) -> key2));
		Map<String, Map<String, Object>> lastYearMonthMap = lastYearMonth.stream()
				.collect(Collectors.toMap(t -> MapUtils.getString(t, "gatherDevId"), Function.identity(), (key1, key2) -> key2));
		
		// 按照设备运行时长从大到小排序
		currentMonth.stream().sorted(Comparator.comparing(t -> MapUtils.getDouble((Map) t, "value")).reversed());
		List<DeviceRunTimeAnalysisVO> list = Lists.newArrayList();
		DeviceRunTimeAnalysisVO vo = null;
		for(Map<String, Object> map : currentMonth) {
			vo = new DeviceRunTimeAnalysisVO();
			vo.setName(MapUtils.getString(map, "name"));// 设备名称
			vo.setCurrentMonthTime(MapUtils.getDouble(map, "value"));// 当月设备运行时长
			vo.setLastMonthTime(Optional.ofNullable(lastMonthMap.get(MapUtils.getString(map, "gatherDevId"))).map(t -> MapUtils.getDouble(t, "value")).orElse(null));
			vo.setLastYearMonthTime(Optional.ofNullable(lastYearMonthMap.get(MapUtils.getString(map, "gatherDevId"))).map(t -> MapUtils.getDouble(t, "value")).orElse(null));
			list.add(vo);
		}
		return list;
	}
	
	/**
	 * 计算设备运行时长
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	@Deprecated
	private List<Map<String, Object>> calculateDeviceRunTime(LocalDateTime startTime, LocalDateTime endTime) {
		/*1.计算每个设备点位的运行时长*/
		// 查询设备点位运行时长
		List<DeviceRunTimeVO> deviceRunTimeList = workOrderDAO.runTimeAnalysis(startTime, endTime);
		// 按设备点位进行分组
		Map<Long, List<DeviceRunTimeVO>> deviceRunTimeMap = deviceRunTimeList.stream().collect(Collectors.groupingBy(DeviceRunTimeVO :: getGatherPointId));
		
		List<Map<String, Object>> pointList = Lists.newArrayList();
		Map<String, Object> pointMap = null;
		List<DeviceRunTimeVO> tempList = null;// 接收分组后设备点位列表临时变量，用来判断、取值等操作
		for (Map.Entry<Long, List<DeviceRunTimeVO>> entry : deviceRunTimeMap.entrySet()) {
			tempList = entry.getValue();
			if(CollectionUtils.isEmpty(tempList)) {
				continue;
			}
			// 按照采集日期升序排序
			tempList = tempList.stream().sorted(Comparator.comparing(DeviceRunTimeVO :: getCollectTime)).collect(Collectors.toList());
			// 取设备点位第一条数据
			double firstValue = tempList.get(0).getValue();
			// 取设备点位最后一条数据
			double lastValue = tempList.get(tempList.size() - 1).getValue();
			// 计算设备点位运行时间
			double diff = lastValue - firstValue;
			
			pointMap = Maps.newHashMap();
			pointMap.put("name", tempList.get(0).getName());// 设备名称
			pointMap.put("gatherDevId", tempList.get(0).getGatherPointId());// 采集设备id
			pointMap.put("gatherPointId", entry.getKey());// 采集点位id
			pointMap.put("value", diff);// 根据累计运行时间计算得出的运行时间
			pointList.add(pointMap);
		}
		
		/*计算每个设备的运行时长，比较每个点位的运行时长，取最大的那个运行时间作为该设备的运行时间*/
		Map<String, Object> devMap = null;
		List<Map<String, Object>> devList = Lists.newArrayList();
		List<Map<String, Object>> tempDevList = null;// 接收分组后设备列表临时变量，用来判断、取值等操作
		if(CollectionUtils.isNotEmpty(pointList)) {
			// 按照设备进行分组，取该设备点位中最大运行时间
			Map<String, List<Map<String, Object>>> devPointMap = pointList.stream().collect(Collectors.groupingBy(t -> MapUtils.getString(t, "gatherDevId")));
			for(Map.Entry<String, List<Map<String, Object>>> entry : devPointMap.entrySet()) {
				tempDevList = entry.getValue();
				if(CollectionUtils.isEmpty(tempDevList)) {
					continue;
				}
				
				devMap = Maps.newHashMap();
				devMap.put("name", MapUtils.getString(tempDevList.get(0), "name"));// 设备名称
				devMap.put("gatherDevId", entry.getKey());// 采集设备id
				devMap.put("value", tempDevList.stream().mapToDouble(t -> MapUtils.getDouble(t, "value")).max());// 取最大值
				devList.add(devMap);
			}
		}
		return devList;
	}
}